<template>
  <div
    v-loading="loading"
    class="app-container uni-scroll"
    style="height: calc(100vh - 100px);"
  >

    <div class="mb-3 flex justify-between">
      <div class="ml-5">
        <span style="color: #34bfa3;">{{ formatSensorType() }}{{ $t('port') }}:{{ port }}</span>
        <span class="text-gray-400 ml-1">{{ sensorName }}</span>
      </div>
      <div class="mr-3">
        <el-button-group>
          <el-button
            round
            type="primary"
            @click="searchDay"
          >24{{ $t('hour') }}
          </el-button>
          <el-button
            type="primary"
            @click="searchWeek"
          >{{ $t('one') + $t('week') }}
          </el-button>
          <el-button
            type="primary"
            @click="searchMonth"
          >{{ $t('one') + $t('month') }}
          </el-button>
          <el-button
            type="primary"
            @click="search3month"
          >{{ $t('three') + $t('month') }}
          </el-button>
        </el-button-group>
        <el-date-picker
          v-model="startDate"
          type="datetime"
          :placeholder="$t('startDate')"
          align="right"
          :picker-options="pickerOptions1"
          value-format="timestamp"
          style=";margin-right: 5px"
        />
        <el-date-picker
          v-model="endDate"
          type="datetime"
          :placeholder="$t('endDate')"
          align="right"
          :picker-options="pickerOptions1"
          value-format="timestamp"
          style=";margin-right: 5px"
        />
        <el-button-group>
          <el-button
            type="primary"
            icon="el-icon-search"
            @click="listWithExplain"
          >{{ $t('search') }}
          </el-button>
          <el-button
            type="primary"
            icon="el-icon-download"
            @click="download"
          >{{ $t('download') }}
          </el-button>
          <el-button
            round
            type="primary"
            :icon="showMulti?'el-icon-arrow-up':'el-icon-arrow-down'"
            @click="showMulti = !showMulti"
          />
        </el-button-group>
      </div>
    </div>
    <multi-line-chart
      v-show="showMulti"
      style="height: 450px;margin-left: 10px;width: 100%;"
      :chart-data="multiLineData"
    />
    <el-row id="canvasList" :gutter="2" class="mt-3">
      <el-col
        v-if="staticList.length > 0"
        :xs="12"
        :sm="12"
        :md="8"
        :lg="8"
        :xl="8"
      >
        <div
          class="item uni-scroll"
          style="height: 353px;margin-bottom: 5px"
        >
          <div
            v-for="(item,index) in staticList"
            v-if="showHidden === '1' || !item.hidden"
            :key="index"
            style="margin:5px 20px;"
          >
            <div
              style="display: flex;height: 52px;padding: 8px;justify-content: space-between"
              @click="explainInfo(item)"
            >
              <div style="display: flex;">
                <div @click.stop="">
                  <device-explain-icon :explain="item"/>
                </div>
                <div style="font-size:13px;margin-left: 5px">
                  <div class="primary-color;font-weight: lighter">
                    <el-popover
                      v-if="item.remark && item.remark!==''"
                      placement="top"
                      width="200"
                      trigger="hover"
                      :content="item.name"
                    >
                      <span slot="reference">{{ item.remark }}</span>
                    </el-popover>
                    <span v-else>{{ item.name }}</span>
                  </div>
                  <div style="font-size:12px;color: #909399;margin-top: 2px">{{ formatDate(item.valueDate) }}</div>
                </div>
              </div>
              <div style="font-size:18px;color: #909399;font-weight: lighter;line-height: 25px">
                <span>{{ item.value }}</span>
                <span style="font-size:15px">{{ item.unit }}</span>
                <i
                  v-if="enableEval === '1' && item.value != '' && !isNaN(Number(item.value)) && item.lastValue != '' && !isNaN(Number(item.lastValue))"
                  :class="item.value > item.lastValue ? 'el-icon-top':'el-icon-bottom'"
                />
                <i
                  v-else-if="item.value != '' && !isNaN(Number(item.value)) && item.lastValue != '' && !isNaN(Number(item.lastValue))"
                  :class="item.rawValue > item.lastRawValue ? 'el-icon-top':'el-icon-bottom'"
                />
              </div>
            </div>
          </div>
        </div>
      </el-col>
      <el-col
        v-for="(item,index) in canvasList"
        :key="index"
        :xs="item.zooMax ? 24 : 12"
        :sm="item.zooMax ? 24 : 12"
        :md="item.zooMax ? 16 : 8"
        :lg="item.zooMax ? 16 : 8"
        :xl="item.zooMax ? 16 : 8"
      >
        <template v-if="item.type!=='hidden' && (showSort || showHidden === '1' || !item.hidden)">
          <div :class="['item', {'sort-border':showSort}]" style="padding:5px;margin-bottom: 5px">
            <div style="margin: 0 20px;display: flex;justify-content: space-between">
              <div style="display: flex">
                <device-explain-icon :explain="item" style="margin: 2px"/>
                <div style="flex-grow: 1;margin-left: 5px">
                  <div style="font-size:13px;font-weight: lighter;">
                    <span class="primary-color;">
                      <el-popover
                        v-if="item.remark && item.remark!==''"
                        placement="top"
                        width="200"
                        trigger="hover"
                        :content="item.name"
                      >
                        <span slot="reference">{{ item.remark }}</span>
                      </el-popover>
                      <span v-else>{{ item.name }}</span>
                    </span>
                    <span
                      v-if="enableEval === '1' ? item.value.length < 6 : item.rawValue.length < 6"
                      style="float: right;color: #909399;"
                    >{{ enableEval === '1' ? item.value : item.rawValue }}<span class="ml-1">{{
                        item.unit
                      }}</span></span>
                    <i
                      v-if="enableEval === '1' && item.value != '' && !isNaN(Number(item.value)) && item.lastValue != '' && !isNaN(Number(item.lastValue))"
                      :class="item.value > item.lastValue ? 'el-icon-top':'el-icon-bottom'"
                    />
                    <i
                      v-else-if="item.rawValue != '' && !isNaN(Number(item.rawValue)) && item.lastRawValue != '' && !isNaN(Number(item.lastRawValue))"
                      :class="item.rawValue > item.lastRawValue ? 'el-icon-top':'el-icon-bottom'"
                    />
                  </div>
                  <div style="font-size:12px;color: #909399;margin-top: 2px">{{ formatDate(item.valueDate) }}</div>
                </div>
              </div>
              <el-button-group>
                <el-button
                  :type="item.warnNum > 0 ? 'danger':''"
                  icon="el-icon-more"
                  @click="explainInfo(item)"
                />
                <el-button
                  v-if="!item.zooMax"
                  icon="el-icon-full-screen"
                  @click="zooMax(item)"
                />
                <el-button
                  v-else
                  icon="el-icon-crop"
                  @click="zooMin(item)"
                />
                <el-button
                  v-if="showSort && !item.hidden"
                  type="danger"
                  icon="el-icon-close"
                  @click="hiddenExplain(item)"
                />
                <el-button
                  v-else-if="showSort"
                  icon="el-icon-view"
                  @click="showExplain(item)"
                />
              </el-button-group>
            </div>

            <line-chart v-if="item.type === 'line'" :chart-data="item" style="width: 100%;height:300px "/>
            <multi-line-chart
              v-else-if="item.type === 'line:multi'"
              style="height: 300px;width: 100%;"
              :chart-data="item.data"
            />
            <el-table
              v-else
              :data="item.data"
              style="width: 94%;margin: 0 auto"
              height="300"
              :show-header="false"
            >
              <el-table-column prop="value"/>
              <el-table-column prop="date"/>
            </el-table>
          </div>
        </template>
      </el-col>
    </el-row>
    <div style="margin: 13px;">
      <el-button-group style=";margin-right: 5px">
        <el-button
          round
          type="primary"
          icon="el-icon-menu"
          @click="gotoParam"
        >{{ $t('param') }}
        </el-button>
        <el-button
          type="primary"
          icon="el-icon-printer"
          @click="gotoExplain"
        >{{ $t('explain') }}
        </el-button>
        <el-button
          icon="el-icon-s-platform"
          type="primary"
          @click="gotoRealTime"
        >{{ $t('realTime') }}
        </el-button>
        <el-button
          icon="el-icon-rank"
          round
          type="primary"
          @click="showSort=!showSort"
        >{{ $t('rank') }}
        </el-button>
      </el-button-group>
      <el-switch
        v-model="filterRepeat"
        style=";margin-right: 5px"
        active-value="1"
        inactive-value="0"
        :active-text="$t('filter')+$t('repeat')"
        @change="filterRepeatChange"
      />
      <el-switch
        v-model="enableEval"
        active-value="1"
        inactive-value="0"
        :active-text="$t('enable')+$t('script')"
        @change="enableEvalChange"
      />
      <el-switch
        v-model="showHidden"
        active-value="1"
        inactive-value="0"
        :active-text="$t('show') + $t('hidden')"
        @change="showHiddenChange"
      />
      <el-switch
        v-model="addFrame"
        active-value="1"
        inactive-value="0"
        :active-text="$t('add')+$t('frame')"
        @change="addFrameChange"
      />
    </div>

    <el-dialog
      :title="explain.name"
      :visible.sync="dialogExplainInfoFormVisible"
      width="1300px"
      top="50px"
    >
      <device-explain-info v-if="dialogExplainInfoFormVisible" :explain="explain"/>
    </el-dialog>

    <el-dialog
      :visible.sync="showSetting"
      :title="deviceName"
      width="1200px"
      top="15px"
    >
      <device-setting
        :sensor-id="sensorId"
        :device-core="deviceCore"
        class="uni-scroll"
        style="height: 600px"
      />
    </el-dialog>

    <el-button
      icon="el-icon-setting"
      circle
      type="primary"
      style="position: fixed;bottom: 30px;right: 20px;z-index: 1000"
      @click="deviceSetting"
    />

  </div>
</template>

<script>
import LineChart from '@/components/Chart/LineChart'
import MultiLineChart from '@/components/Chart/MultiLineChart'
import DeviceExplainIcon from '@/components/DeviceExplainIcon'
import { failureNotice, formatDate, formatSensorType } from '@/util/common'
import { listWithExplain } from '@/api/iot/iotDeviceSensorDataApi'
import { updateExplain, updateExplainList } from '@/api/iot/iotDeviceExplainApi'
import DeviceSetting from '@/components/DeviceSetting'
import DeviceExplainInfo from '@/components/DeviceExplainInfo'
import Sortable from 'sortablejs'
import resize from '@/components/Mixins/resize'

import {
  getAddFrame,
  getEnableEval,
  getFilterRepeat,
  getShowHidden,
  setAddFrame,
  setEnableEval,
  setFilterRepeat,
  setShowHidden
} from '@/util/storage'
import { downloadExcel } from '@/util/file'

export default {
  name: 'SensorHistory',
  components: {
    LineChart,
    MultiLineChart,
    DeviceSetting,
    DeviceExplainInfo,
    DeviceExplainIcon
  },
  mixins: [resize],
  data() {
    return {
      showMulti: true,
      multiLineData: {
        dataList: [],
        dateList: []
      },
      explain: {},
      dialogExplainInfoFormVisible: false,
      deviceName: null,
      deviceCore: null,
      sensorName: null,
      sensorId: null,
      port: null,
      type: null,
      startDate: null,
      endDate: null,
      pickerOptions1: {
        shortcuts: [
          {
            text: this.$t('today'),
            onClick(picker) {
              picker.$emit('pick', new Date())
            }
          },
          {
            text: this.$t('today'),
            onClick(picker) {
              const date = new Date()
              date.setTime(date.getTime() - 3600 * 1000 * 24)
              picker.$emit('pick', date)
            }
          },
          {
            text: this.$t('a') + this.$t('week') + this.$t('ago'),
            onClick(picker) {
              const date = new Date()
              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
              picker.$emit('pick', date)
            }
          }
        ]
      },
      showSetting: false,
      canvasList: [],
      rankExplainList: [],
      staticList: [],
      showSort: false,
      loading: false,
      filterRepeat: getFilterRepeat(),
      enableEval: getEnableEval(),
      showHidden: getShowHidden(),
      addFrame: getAddFrame(),
      dataList: []
    }
  },
  mounted() {
    const param = this.$route.query
    this.sensorId = param.sensorId ? parseInt(param.sensorId) : null
    this.type = param.type
    this.deviceCore = param.deviceCore
    this.deviceName = param.deviceName
    this.sensorName = param.sensorName
    this.port = param.port
    const timestamp = new Date().getTime() + 5 * 60 * 60 * 1000
    this.startDate = new Date().getTime() - 7 * 24 * 60 * 60 * 1000
    this.endDate = timestamp
    this.listWithExplain()
    this.setTagsViewTitle()
  },
  methods: {
    formatSensorType() {
      return formatSensorType(this, parseInt(this.type))
    },
    filterRepeatChange() {
      setFilterRepeat(this.filterRepeat)
      this.listWithExplain()
    },
    enableEvalChange() {
      setEnableEval(this.enableEval)
      this.listWithExplain()
    },
    showHiddenChange() {
      setShowHidden(this.showHidden)
    },
    addFrameChange() {
      setAddFrame(this.addFrame)
    },
    formatterSeconds(time) {
      if (time > 60) {
        return (time / 60) + this.$t('minutes')
      } else {
        return time + this.$t('seconds')
      }
    },
    formatDate(time) {
      return formatDate(this, time)
    },
    deviceSetting() {
      this.showSetting = true
    },
    setTagsViewTitle() {
      this.tempRoute = Object.assign({}, this.$route)
      const route = Object.assign({}, this.tempRoute, {
        title: `${this.deviceName}`
      })
      this.$store.dispatch('tagsView/updateVisitedView', route)
    },
    zooMax(item) {
      const type = item.type
      item.type = 'hidden'
      this.$nextTick(() => {
        item.type = type
        item.zooMax = true
      })
    },
    zooMin(item) {
      const type = item.type
      item.type = 'hidden'
      this.$nextTick(() => {
        item.type = type
        item.zooMax = false
      })
    },
    hiddenExplain(item) {
      const hidden = true
      const json = {
        hidden: hidden,
        explainId: item.explainId
      }
      updateExplain(json).then(res => {
        const { code } = res
        if (code === '200') {
          item.hidden = hidden
        }
      })
    },
    showExplain(item) {
      const hidden = false
      updateExplain({
        explainId: item.explainId,
        hidden: hidden
      }).then(res => {
        const { code } = res
        if (code === '200') {
          item.hidden = hidden
        }
      })
    },
    explainInfo(index) {
      this.explain = index
      this.dialogExplainInfoFormVisible = true
    },
    download() {
      /**
       * 保存下载数据
       * @type {Array}
       */
      const downloadData = []
      let valMap
      const downloadColumnNameList = []
      const tempMap = {}
      for (let k = 0, l = this.dataList.length; k < l; k++) {
        valMap = this.dataList[k].val
        const valueMap = {}
        for (let i = 0, j = this.explainList.length; i < j; i++) {
          const explain = this.explainList[i]
          if (explain.type === 'static') {
            continue
          }
          if (k === 0) {
            downloadColumnNameList.push(explain.name)
          }
          if (typeof (valMap[explain.keyName]) !== 'undefined') {
            valueMap[explain.keyName] = valMap[explain.keyName] + explain.unit
            tempMap[explain.keyName] = valMap[explain.keyName] + explain.unit
          } else if (this.addFrame === '1') {
            if (tempMap[explain.keyName]) {
              valueMap[explain.keyName] = tempMap[explain.keyName]
            } else {
              valueMap[explain.keyName] = ''
            }
          } else {
            valueMap[explain.keyName] = ''
          }
        }
        valueMap['createdTime'] = this.dataList[k].createdTime
        downloadData.push(valueMap)
      }
      downloadColumnNameList.push(this.$t('date'))
      downloadExcel(this.deviceName + '-' + this.sensorName, downloadColumnNameList, downloadData)
    },
    listWithExplain() {
      this.loading = true
      listWithExplain({
        sensorId: this.sensorId,
        startTime: Math.round(this.startDate / 1000),
        endTime: Math.round(this.endDate / 1000),
        enableEval: this.enableEval === '1',
        filterRepeat: this.filterRepeat === '1'
      }).then(res => {
        const { data, code } = res
        if (code === '200') {
          const { dataList, explainList } = data
          this.dataList = dataList
          this.explainList = explainList
          if (!explainList || explainList.length === 0) {
            failureNotice(this, this.$t('no') + this.$t('explain'))
            this.loading = false
            return
          }

          this.rankExplainList = JSON.parse(JSON.stringify(explainList))

          /**
           * 装换时间
           */
          const checkDX = []

          for (let i = 0, j = dataList.length; i < j; i++) {
            const item = dataList[i]
            const commonTime = formatDate(this, item.createdTime)
            item.createdTime = commonTime
            checkDX.push(commonTime)
          }

          const canvasList = []
          const checkGroupLists = []
          const staticList = []
          const explainLastValueMap = {}

          for (let i = 0, j = explainList.length; i < j; i++) {
            const explain = explainList[i]
            const item = {
              ...explain,
              index: i,
              zooMax: false
            }
            if (explain.type === 'static' || explain.type === 'static:multi') {
              staticList.push(explain)
            } else {
              if (explain.type === 'line') {
                const dy = []
                const dx = []
                const checkDy = []
                let valMap
                for (let k = 0, l = dataList.length; k < l; k++) {
                  const dataItem = dataList[k]
                  valMap = dataItem.val
                  if (typeof (valMap[explain.keyName]) !== 'undefined') {
                    explainLastValueMap[explain.keyName] = valMap[explain.keyName]
                    dy.push(valMap[explain.keyName])
                    dx.push(dataItem.createdTime)
                    checkDy.push(valMap[explain.keyName])
                  } else if (this.addFrame === '1') {
                    dy.push(explainLastValueMap[explain.keyName] || this.enableEval === '1' ? explain.value : explain.rawValue)
                    dx.push(dataItem.createdTime)
                    checkDy.push(explainLastValueMap[explain.keyName])
                  } else {
                    checkDy.push(explainLastValueMap[explain.keyName])
                  }
                }
                if (dx.length === 0) {
                  dy.push(explain.value)
                  dx.push(formatDate(this, explain.valueDate))
                }
                checkGroupLists.push({
                  name: explain.name,
                  unit: explain.unit,
                  dataList: checkDy
                })

                item.dataList = dy
                item.dateList = dx
                canvasList.push(item)
              } else if (explain.type === 'line:multi') {
                let valMap
                const xList = []
                const yList = []
                for (let k = 0, l = dataList.length; k < l; k++) {
                  valMap = dataList[k].val
                  if (typeof (valMap[explain.keyName]) !== 'undefined') {
                    xList.push(dataList[k].createdTime)
                    const valList = valMap[explain.keyName].split(',')
                    for (let n = 0, m = valList.length; n < m; n++) {
                      const yd = valList[n]
                      let have = false
                      for (const yItem of yList) {
                        if (yItem.name === n) {
                          yItem.dataList.push(yd)
                          have = true
                          break
                        }
                      }
                      if (!have) {
                        yList.push({
                          name: n,
                          unit: explain.unit,
                          dataList: [yd]
                        })
                      }
                    }
                  }
                }
                item.data = {
                  dateList: xList,
                  dataList: yList
                }
                canvasList.push(item)
              } else {
                const data = []
                for (let k = 0, l = dataList.length; k < l; k++) {
                  const valMap = dataList[k].val
                  if (typeof (valMap[explain.keyName]) !== 'undefined') {
                    data.push({
                      value: valMap[explain.keyName],
                      date: dataList[k].createdTime
                    })
                  }
                }
                if (data.length === 0) {
                  data.push({
                    value: explain.value,
                    date: formatDate(this, explain.valueDate)
                  })
                }
                item.data = data
                canvasList.push(item)
              }
            }
          }
          this.multiLineData = {
            dateList: checkDX,
            dataList: checkGroupLists
          }

          this.canvasList = canvasList
          this.staticList = staticList
          this.setSortable()
          this.loading = false
        }
      })
    },
    setSortable() {
      const $ul = document.getElementById('canvasList')
      new Sortable($ul, {
        setData(dataTransfer) {
          dataTransfer.setData('Text', '')
        },
        onEnd: evt => {
          const targetRow = this.rankExplainList.splice(evt.oldIndex, 1)[0]
          this.rankExplainList.splice(evt.newIndex, 0, targetRow)
          if (this.showSort) {
            const explainList = []
            for (let i = 0, j = this.rankExplainList.length; i < j; i++) {
              const data = {
                rankNumber: i,
                explainId: this.rankExplainList[i].explainId
              }
              explainList.push(data)
            }
            updateExplainList({
              explainList: explainList
            })
          }
        },
        animation: 150
      })
    },
    search3month() {
      const timestamp = new Date().getTime()
      this.startDate = new Date().getTime() - 3 * 31 * 24 * 60 * 60 * 1000
      this.endDate = timestamp
      this.listWithExplain()
    },
    searchMonth() {
      const timestamp = new Date().getTime()
      this.startDate = new Date().getTime() - 31 * 24 * 60 * 60 * 1000
      this.endDate = timestamp
      this.listWithExplain()
    },
    searchDay() {
      const timestamp = new Date().getTime()
      this.startDate = new Date().getTime() - 24 * 60 * 60 * 1000
      this.endDate = timestamp
      this.listWithExplain()
    },
    searchWeek() {
      const timestamp = new Date().getTime()
      this.startDate = new Date().getTime() - 7 * 24 * 60 * 60 * 1000
      this.endDate = timestamp
      this.listWithExplain()
    },
    gotoRealTime() {
      this.$router.push({
        path: '/device/sensor/real-time/' + this.sensorId,
        query: {
          port: this.port,
          type: this.type,
          sensorId: this.sensorId,
          deviceName: this.deviceName,
          deviceCore: this.deviceCore,
          sensorName: this.sensorName
        }
      })
    },

    gotoParam() {
      this.$router.push({
        path: '/device/param/' + this.deviceCore,
        query: {
          port: this.port,
          sensorId: this.sensorId,
          deviceName: this.deviceName,
          deviceCore: this.deviceCore,
          sensorName: this.sensorName
        }
      })
    },

    gotoExplain() {
      this.$router.push({
        path: '/device/explain/' + this.deviceCore,
        query: {
          port: this.port,
          sensorId: this.sensorId,
          deviceName: this.deviceName,
          deviceCore: this.deviceCore,
          sensorName: this.sensorName
        }
      })
    }
  }
}
</script>
<style scoped>
.sort-border {
  border-style: dashed;
  border-color: #6E6F71;
  border-width: 1px;
  border-radius: 12px;
}

.item {
  height: 353px;
}

.item:hover {
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
  border-radius: 12px;
}

</style>
